﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.WVB.Framework;
using System.Windows;
using Microsoft.WVB.Silverlight.Infrastructure;

namespace Microsoft.WVB.UnitTest.Client.DIContainerTest
{
    #region Test Services
    interface ITest
    {
        string Hey();
        uint Age { get; }
    }
    class ClassA : ITest
    {
        public string Hey()
        {
            return "Hey from ClassA";
        }
        public uint Age
        {
            get { return 42; }
        }
    }
    class ClassB : ITest
    {
        public ClassB(uint age)
        {
            _age = age;
        }
        public string Hey()
        {
            return "Hey from ClassB";
        }
        private uint _age = 21;
        public uint Age
        {
            get { return _age; }
        }
    }
    #endregion
    
    [TestClass]
    public class IoC_DIContainerTest
    {
        [TestInitialize]
        public void Initialize()
        {
            Application.Current.Resources.Clear();
            IoC.InitializeApplicationResources(Application.Current);
        }
        [TestCleanup]
        public void Cleanup()
        {
            Application.Current.Resources.Clear();
        }
        [TestMethod]
        public void TestCreate()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ITest>((container) => new ClassA());
            ITest t = dic.Create<ITest>();
            Assert.AreEqual(t.Age.ToString(), 42.ToString());
        }
        [TestMethod]
        public void TestGetCreate()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ITest>((container) => new ClassA());
            ITest t = dic.GetCreate<ITest>();
            Assert.AreEqual(t.Age.ToString(), 42.ToString());
        }
        [TestMethod]
        public void TestGetCreate2()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ITest>((container) => new ClassA());
            ITest t = dic.GetCreate<ITest>();
            ITest t2 = dic.GetCreate<ITest>();
            Assert.AreSame(t, t2);
        }
        [TestMethod]
        public void TestGetCreate3()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ITest>((container) => new ClassA());
            ITest t = dic.GetCreate<ITest>();
            ITest t2 = dic.Get<ITest>();
            Assert.AreSame(t, t2);
        }
        [TestMethod]
        public void TestClear()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ITest>((container) => new ClassA());
            ITest t = dic.GetCreate<ITest>();
            ITest t2 = dic.Get<ITest>();
            dic.RemoveInstance<ITest>();
            try
            {
                dic.Get<ITest>();
                Assert.Fail("Method should have thrown exception");
            }
            catch
            {
                Assert.IsTrue(true,"Good job");
            }
        }
        [TestMethod]
        public void TestInstance_GetNotThere()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ITest>((container) => new ClassA());
            ITest t = dic.Create<ITest>();
            try
            {
                dic.Get<ITest>();
                Assert.Fail("Method should have thrown exception");
            }
            catch
            {
                Assert.IsTrue(true, "Good job");
            }
        }
        [TestMethod]
        public void TestParameterizedConstruction()
        {
            DIContainer dic = new DIContainer();
            dic.Configuration["consts.age"] = (uint)50;
            dic.Register<ITest>((c) => new ClassB(c.GetNamedConfigurationItem<uint>("consts.age")));
            ITest t = dic.Create<ITest>();
            Assert.Equals(50, t.Age);
        }
        [TestMethod]
        public void TestParameterizedConstruction2()
        {
            DIContainer dic = new DIContainer();
            dic.Configuration["consts.age"] = (uint)50;
            dic.Register<ITest>((c) => new ClassB(c.GetNamedConfigurationItem<uint>("consts.age")));

            ITest t = dic.Create<ITest>();
            Assert.Equals(50, t.Age);
            
            dic.Configuration["consts.age"] = (uint)52;
            ITest t2 = dic.GetCreate<ITest>();
            Assert.Equals(52, t2.Age);
            dic.Configuration["consts.age"] = (uint)54;
            ITest t3 = dic.GetCreate<ITest>();
            //Setting configuration should not impose any changes on already instantiated instances
            Assert.Equals(t2.Age, t3.Age);

            ITest t4 = dic.Create<ITest>();
            //future instances made with new parameters.
            Assert.Equals(54, t4.Age);
        }
        [TestMethod]
        public void TestParameterizedConstructionInstances()
        {
            DIContainer dic = new DIContainer();
            dic.Configuration["consts.age"] = (uint)50;
            dic.Register<ITest>((c) => new ClassB(c.GetNamedConfigurationItem<uint>("consts.age")));
            ITest t = dic.Create<ITest>();
            ITest t2 = dic.GetCreate<ITest>();
            ITest t3 = dic.GetCreate<ITest>();
            Assert.AreSame(t2,t3);
        }
    }
}
